package xcmg.syn.util;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
import xcmg.syn.manager.config.RedisConfig;
import yb.ecp.fast.infra.infra.log.LogHelper;

/**
 * @author wangyong
 */
@Component
public class JedisUtils {

  @Autowired
  private RedisConfig config;

  private static JedisUtils jedisUtils;

  @Autowired
  private RedisTemplate redisTemplate;

  private static final String REDIS_SCAN_CURSOR_START = "0";

  @PostConstruct
  public void init() {
    jedisUtils = this;
    jedisUtils.config = this.config;
  }

  /**
   * 获取自增数
   *
   * @param key
   * @return
   */
  public static Long incrByKey(String key) {
    if (StringUtils.isBlank(key)) {
      return null;
    }
    Jedis jedis = null;
    Long result = null;
    try {
      JedisPool jedisPool = jedisUtils.config.jedisPool();
      jedis = jedisPool.getResource();
      result = Long.valueOf(jedis.incr(key));
      // 确保循环自增，不超过5位
      if (result > 9998) {
        jedis.del(key);
        result = Long.valueOf(9999);
      }
      // 定时任务会每天清除key从 0 增长，此处确保如定时任务未清除满一天也会清除掉
      jedis.expire(key, 24*60*60);
    } finally {
      if (null != jedis) {
        jedis.close();
      }
    }
    return result;
  }

  /**
   * 获取自增数三位
   *
   * @param key
   * @return
   */
  public static Long incrByKey4Jck(String key) {
    if (StringUtils.isBlank(key)) {
      return null;
    }
    Jedis jedis = null;
    Long result = null;
    try {
      JedisPool jedisPool = jedisUtils.config.jedisPool();
      jedis = jedisPool.getResource();
      result = Long.valueOf(jedis.incr(key));
      // 确保循环自增，不超过5位
      if (result > 998) {
        jedis.del(key);
        result = Long.valueOf(999);
      }
      // 定时任务会每天清除key从 0 增长，此处确保如定时任务未清除满一天也会清除掉
      jedis.expire(key, 24*60*60);
    } finally {
      if (null != jedis) {
        jedis.close();
      }
    }
    return result;
  }

  /**
   * 根据前缀批量删除
   *
   * @param keyPre
   */
  public static void batchDel(String keyPre) {
    if (StringUtils.isBlank(keyPre)) {
      return;
    }
    Jedis jedis = null;
    try {
      JedisPool jedisPool = jedisUtils.config.jedisPool();
      jedis = jedisPool.getResource();
      List<String> keyList = getScan(keyPre);
      for (String key:keyList) {
        jedis.del(key);
      }
    } finally {
      if (null != jedis) {
        jedis.close();
      }
    }
  }

  /**
   * 避免使用keys，scan方式获取所有前缀为keyPre的key
   *
   * @param keyPre
   * @return
   */
  private static List<String> getScan(String keyPre) {
    List<String> list = new ArrayList<>();
    ScanParams params = new ScanParams();
    Jedis jedis = null;
    params.match(keyPre+"*");
    params.count(100);
    // 游标
    String cursor = REDIS_SCAN_CURSOR_START;
    try {
      JedisPool jedisPool = jedisUtils.config.jedisPool();
      jedis = jedisPool.getResource();
      while (true) {
        ScanResult scanResult = jedis.scan(cursor,params);
        List<String> result = scanResult.getResult();
        if (result != null && result.size() > 0) {
          list.addAll(result);
        }
        cursor = scanResult.getCursor();
        if (REDIS_SCAN_CURSOR_START.equals(cursor)) {
          break;
        }
      }
    } finally {
      if (null != jedis) {
        jedis.close();
      }
    }
    return list;
  }

  /**
   * 判断缓存中是否有对应的value
   *
   * @param key
   * @return
   */
  @SuppressWarnings("unchecked")
  public boolean exists(final String key) {
    return redisTemplate.hasKey(key);
  }

  /**
   * 读取缓存
   *
   * @param key
   * @return
   */
  @SuppressWarnings("unchecked")
  public Object get(final String key) {
    ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
    return operations.get(key);
  }

  /**
   * 写入缓存
   *
   * @param key
   * @param value
   * @return
   */
  @SuppressWarnings("unchecked")
  public boolean set(final String key, Object value, Long expireTime) {
    boolean result = false;
    try {
      ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
      operations.set(key, value);
      redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
      result = true;
    } catch (Exception e) {
      LogHelper.fatal("redis is error.", e);
    }
    return result;
  }

  /**
   * 删除缓存
   *
   * @param key
   * @return
   */
  @SuppressWarnings("unchecked")
  public void delete(final String key) {
    redisTemplate.delete(key);
  }
}
